<script setup lang="ts">
import { Message } from '@arco-design/web-vue'
import { useDateFormat, useNow, useStorage } from '@vueuse/core'
import type { Editor, InsertMessage, SendMessage, SocketStatus } from '~/pages/types'
import { emojiList } from '~/utils/emoji'
import { getTalkDetail } from '~/api/index'
import chat from '~/pages/template/chat.vue'
import infoPane from '~/pages/template/infoPane.vue'
import configs from '~/config/index'
import { appendSendParams, getUserInfo } from '~/pages/template/tools'

const props = defineProps<{
  res: any
  status: SocketStatus
  receive: any
}>()

const emit = defineEmits(['send'])
const userTalkList: any = useStorage('talk_list', [])
const scrollbarChat = ref<HTMLElement | any>(null)
const messageType = ref<any>('MESSAGE')

const talkList = ref<any>([])
const backToBottom = ref<boolean>(false)
const textareaRef = ref<any>(null)
const myself = ref<any>('')
const messageLogs = ref<any>({
  loading: false,
  reconnect: 0,
})
const data = ref<Editor>({
  pageNumber: 1,
  sendtime: 0,
  text: '',
  interval: 1000,
  imageViewer: {
    show: false,
    url: '',
  },
})

// #TODO 掉线重连 重新获取聊天记录
// watch(
//   () => props.status,
//   async (val: SocketStatus) => {
//     if (val === 'close')
//       messageLogs.value.reconnect += 1
//     if (val === 'connect' && messageLogs.value.reconnect !== 0) {
//       data.value.pageNumber = 1
//       talkList.value = []
//       await getTalkedDetail()
//     }
//   },
// )

watch(() => props.res?.id, async (val) => {
  if (val) {
    data.value.pageNumber = 1
    talkList.value = []
    await getTalkedDetail()
    nextTick(() => {
      scrollToBottom()
    })
  }
}, { deep: true })

watch(() => props.receive, (val: any) => {
  if (val)
    appendChatToBottom(val)
}, { immediate: true, deep: true })

// 监听消息并追加到聊天框
function appendChatToBottom(chat: any) {
  // 先判断是否是当前聊天框的内容
  if (chat.talkId === props.res.id) {
    talkList.value.push(chat)
    nextTick(() => {
      scrollToBottom()
    })
  }
}

// 发送聊天内容
function keydownEvent(e: any) {
  if (e.keyCode === 13 && !data.value.text)
    e.preventDefault()
  // 回车发送消息
  if (e.keyCode === 13 && e.shiftKey === false && data.value.text) {
    if (props.status !== 'connect') {
      Message.error('当前连接中断，无法发送消息')
      e.preventDefault()
      return false
    }
    // 先判断当前socket是否连接
    if (props.status === 'connect') {
      sendMessage()
      data.value.text = ''

      e.preventDefault()
      nextTick(() => {
        scrollToBottom()
      })
    }
  }
}

function sendMessage() {
  const sendMessage: SendMessage = {
    context: data.value.text,
    messageType: messageType.value,
    operationType: messageType.value,
    ...appendSendParams(),
    // from: myself.value.id,
    // talkId: props.res.id,
    // to: props.res.userId,
  }
  emit('send', sendMessage)
  insertToChat({
    createTime: useDateFormat(useNow(), 'YYYY-MM-DD HH:mm:ss'),
    fromUser: myself.value.id,
    toUser: props.res.userId,
    isRead: false,
    messageType: 'MESSAGE',
    text: data.value.text,
  })
}

function insertToChat(val: InsertMessage) {
  // 用户聊天内容最后一条插入最新
  const talkUser = userTalkList.value.find((item: any) => item.id === props.res.id)
  if (talkUser)
    talkUser.lastTalkMessage = val.text

  // 聊天框插入内容
  talkList.value.push(val)
}

// scroll监听
function talkPanelScroll(e: any) {
  const height = e.target.scrollTop + e.target.clientHeight + 5
  backToBottom.value = height < e.target.scrollHeight
  // 滚动到顶部触发加载事件并且判断当前talkList是否为空
  if (e.target.scrollTop === 0 && talkList.value.length > 0) {
    data.value.pageNumber++
    getTalkedDetail()
  }
}

// 滚动到最底部
function scrollToBottom() {
  const chatContainer = scrollbarChat.value
  if (chatContainer)
    chatContainer.scrollTop = chatContainer.scrollHeight
}

// 获取聊天记录
async function getTalkedDetail() {
  messageLogs.value.loading = true
  const scrollHeight = scrollbarChat.value.scrollHeight
  const res = await getTalkDetail({
    talkId: props.res.id,
    pageNumber: data.value.pageNumber,
  })

  messageLogs.value.loading = false
  if (res.data.success) {
    if (talkList.value)
      talkList.value.unshift(...res.data.result)

    else
      talkList.value.push(...res.data.result)
  }

  nextTick(() => {
    // if (data.record_id == 0 || !data.record_id) {
    if (data.value.pageNumber === 1)
      scrollbarChat.value.scrollTop = scrollbarChat.value.scrollHeight
    else
      scrollbarChat.value.scrollTop = scrollbarChat.value.scrollHeight - scrollHeight
  })
}

// 定义一个方法在光标位置插入文本
function insertTextAtCursor(textToInsert: any) {
  if (textareaRef.value) {
    const textarea = textareaRef.value
    const startPos = textarea.selectionStart
    const endPos = textarea.selectionEnd

    // 获取textarea的当前值并插入新的文本
    const beforeInsert = textarea.value.substring(0, startPos)
    const afterInsert = textarea.value.substring(endPos)
    data.value.text = beforeInsert + textToInsert + afterInsert

    // 设置光标的位置
    const newCursorPos = startPos + textToInsert.length
    textarea.setSelectionRange(newCursorPos, newCursorPos)
    textarea.focus()
  }
}
defineExpose({
  insertToChat,
  scrollToBottom,
})
onMounted(() => {
  // 获取当前用户信息
  if (getUserInfo())
    myself.value = getUserInfo()
})
</script>

<template>
  <div v-auto-animate relative>
    <!-- 顶部 -->
    <div box-border h-80px w-full flex flex-a-c :style="{ background: configs.GRAYCOLOR }" border-b px-16px>
      {{ props.res?.name }}
    </div>
    <div flex>
      <div flex-1>
        <!-- 聊天框 -->
        <div ref="scrollbarChat" relative :style="{ height: 'calc(100vh - 282px)' }" box-border overflow-auto p-16px class="content" @scroll="talkPanelScroll">
          <chat v-for="(item, index) in talkList" :key="index" :res="item" />
        </div>
        <!-- 返回到底部 -->
        <div v-if="backToBottom" class="back" @click="scrollToBottom">
          返回底部
        </div>
        <!-- 工具框 -->
        <div box-border h-40px flex flex-a-c border-y-1px px-16px>
          <!-- 表情 -->
          <a-tooltip content="表情符号" position="bottom">
            <a-popover trigger="click">
              <svg cursor-pointer xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24">
                <path
                  fill="currentColor"
                  d="M12 3a9 9 0 1 0 0 18a9 9 0 0 0 0-18M1 12C1 5.925 5.925 1 12 1s11 4.925 11 11s-4.925 11-11 11S1 18.075 1 12m8-4v4H7V8zm8 0v4h-2V8zm-8.1 5.634l.5.865C9.922 15.4 10.89 16 12 16s2.08-.601 2.6-1.5l.5-.866l1.731 1.001l-.5.866A4.998 4.998 0 0 1 12 18a4.998 4.998 0 0 1-4.33-2.5l-.501-.865z"
                />
              </svg>
              <template #content>
                <div w-400px flex flex-wrap>
                  <div
                    v-for="(emoji, emojiStr) in emojiList.emojis" :key="emojiStr" class="emoji" h-25px w-25px p-2px
                    @click="insertTextAtCursor(emojiStr)" v-html="emoji"
                  />
                </div>
              </template>
            </a-popover>
          </a-tooltip>
        </div>
        <div h-160px>
          <textarea
            ref="textareaRef"
            v-model.trim="data.text" class="textarea" :max-length="1000" placeholder="按住Enter发送" h-155px
            @keydown="keydownEvent"
          />
        </div>
      </div>
      <div v-if="props.res" min-w-340px>
        <!-- 右侧信息栏 -->
        <infoPane h-full border-l-1px />
      </div>
    </div>
  </div>
</template>

<style scoped>
.content {
  height: calc(100vh - 260px);
}

.emoji:hover {
  transform: scale(1.6);
  cursor: pointer;
}

textarea {
  width: calc(100% - 10px);
  width: -moz-calc(100% - 10px);
  width: -webkit-calc(100% - 10px);
  height: calc(100% - 10px);
  height: -moz-calc(100% - 10px);
  height: -webkit-calc(100% - 10px);
  border: 0 none;
  outline: none;
  resize: none;
  font-size: 15px;
  overflow-y: auto;
  color: #464545;
  padding: 5px;
  position: relative;
}

textarea::-webkit-scrollbar {
  width: 4px;
  height: 1px;
}

textarea::-webkit-scrollbar-thumb {
  background: #d5cfcf;
}

textarea::-webkit-scrollbar-track {
  background: #ededed;
}

textarea::-webkit-input-placeholder {
  color: #dccdcd;
  font-size: 12px;
  font-weight: 400;
}
.back {
  cursor: pointer;
  display: flex;
  justify-content: center;
  align-items: center;
  position: absolute;
  left: -330px;
  right: 0;
  margin: 0 auto;
  bottom: 240px;
  height: 30px;
  width: 100px;
  border-radius: 20px;
  font-size: 12px;
  background-color: #fff;
  color: #1f2329;
  border: 1px solid #e6e6e6;
}
</style>
